﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace FNN.Genetic.Mutations
{
    public class LayerMutation : Mutation
    {
        /// <summary>
        ///     Конструктор на основе типа мутации
        /// </summary>
        /// <param name="mutationType">Тип мутации</param>
        public LayerMutation(MutationTypes mutationType)
        {
            MutationTargetValue = MutationTargets.Layer;
            MutationTypeValue = mutationType;
        }

        /// <summary>
        ///     Конструктор на основе ДНК и типа мутации
        /// </summary>
        /// <param name="targetDna">Целевая ДНК</param>
        /// <param name="mutationType">Тип мутации</param>
        public LayerMutation(DnaHelix targetDna, MutationTypes mutationType)
        {
            MutationTargetValue = MutationTargets.Layer;
            MutationTypeValue = mutationType;
            TargetDnaValue = targetDna;
        }

        /// <summary>
        ///     Запустить мутацию
        /// </summary>
        public override void Execute()
        {
            var targetChain = TargetDnaValue.LayersChain;
            var targetList = targetChain.Split('|').ToList();
            int randomLayerSize, randomLayerPosition;
            var randomNeuronList = new List<int>();

            switch (MutationTypeValue)
            {
                case MutationTypes.Additive:
                    randomLayerSize = MutationRandomizer.Next(1, 10);
                    randomLayerPosition = MutationRandomizer.Next(0, targetList.Count + 1);
                    for (int i = 0; i < randomLayerSize; i++)
                    {
                        randomNeuronList.Add(MutationRandomizer.Next(0, 6));
                    }
                    targetList.Insert(randomLayerPosition, String.Join(";", randomNeuronList));
                    break;
                case MutationTypes.Destructive:
                    randomLayerPosition = MutationRandomizer.Next(0, targetList.Count + 1);
                    targetList.Remove(targetList.ElementAt(randomLayerPosition));
                    break;
                case MutationTypes.Transformative:
                    randomLayerSize = MutationRandomizer.Next(1, 11);
                    randomLayerPosition = MutationRandomizer.Next(0, targetList.Count);
                    for (int i = 0; i < randomLayerSize; i++)
                    {
                        randomNeuronList.Add(MutationRandomizer.Next(0, 6));
                    }
                    targetList[randomLayerPosition] = String.Join(";", randomNeuronList);
                    break;
            }
            targetChain = String.Join("|", targetList);
            TargetDnaValue.SynapsesChain = targetChain;
        }

        /// <summary>
        ///     Запустить мутацию с параметрами
        /// </summary>
        /// <param name="targetDna">Целевая ДНК</param>
        /// <param name="mutationType">Тип мутации</param>
        public override void Execute(DnaHelix targetDna, MutationTypes mutationType)
        {
            TargetDnaValue = targetDna;
            MutationTypeValue = mutationType;
            MutationTargetValue = MutationTargets.Layer;
            Execute();
        }
    }
}
